﻿/* 
This file is part of Ingo Karstein's SharePoint PowerShell Timer Jobs project

**Do not remove this comment**

Please see the project homepage at CodePlex:
  http://sppowershelltimerjob.codeplex.com/

Please see my blog:
  http://ikarstein.wordpress.com

Licence: GPLv2
    Ingo Karstein's SharePoint PowerShell Timer Jobs
    Copyright (C) 2011  Ingo Karstein, ikarstein@hotmail.com

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.Administration;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Management.Automation.Host;
using System.Collections.ObjectModel;
using Microsoft.SharePoint;
using System.Diagnostics;
using System.Threading;

namespace ik.SharePoint2010.SPPowerShellTimerJob
{
    class SPPowerShellJobDefinition : SPJobDefinition, IPSApp
    {
        private Guid fld_Title = new Guid("{fa564e0f-0c70-4ab9-b863-0177e6ddd247}");
        private Guid fld_ikServerName = new Guid("{6C441249-AFA5-41A8-9964-BC7BD16826B1}");
        private Guid fld_ikTimestamp = new Guid("{E58B26C8-AB63-421A-94E6-BB69C81F75E2}");
        private Guid fld_ikResultText = new Guid("{B41BCDB8-BBB5-4713-82A1-85A6F417E226}");
        private Guid fld_ikErrorOccured = new Guid("{9800647D-FA1C-420F-84B4-DC820A091808}");

        private StringBuilder sb;

        public SPPowerShellJobDefinition()
            : base()
        {
            Title = "PowerShell Job";
        }

        public SPPowerShellJobDefinition(string name, SPService service, SPServer server, SPJobLockType lockType)
            : base(name, service, server, lockType)
        {
            Title = name;
        }

        public SPPowerShellJobDefinition(string name, SPWebApplication webApp, SPServer server, SPJobLockType lockType)
            : base(name, webApp, server, lockType)
        {
            Title = name;
        }

        public string PowerShellScript
        {
            get
            {
                return this.Properties["PSScript"] as string;
            }
            set
            {
                this.Properties["PSScript"] = value;
                this.Update();
            }
        }

        public override bool OnBackup(object sender, Microsoft.SharePoint.Administration.Backup.SPBackupInformation info)
        {
            return base.OnBackup(sender, info);
        }

        public override void Execute(Guid targetInstanceId)
        {
            base.Execute(targetInstanceId);
            DateTime start = DateTime.Now;
            Stopwatch sw = new Stopwatch();
            sw.Start();

            sb = new StringBuilder();

            try
            {
                PSHostUI ui = new PSHostUI();
                ui.ParentApp = this;
                PS2EXEHost host = new PS2EXEHost(this, ui);

                using( Runspace myRunSpace = RunspaceFactory.CreateRunspace(host) )
                {
                    myRunSpace.Open();

                    using( System.Management.Automation.PowerShell powershell = System.Management.Automation.PowerShell.Create() )
                    {
                        powershell.Runspace = myRunSpace;

                        powershell.AddScript("Add-PSSnapIn Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue | out-null\r\n" +
                                             "$o = Invoke-Command -ScriptBlock {\r\n" +
                                             PowerShellScript +
                                             "\r\n} \r\n $p = $o | out-string\r\n$p");

                        powershell.Streams.Progress.DataAdded += new EventHandler<DataAddedEventArgs>(delegate(object sender, DataAddedEventArgs e)
                            {
                                sb.AppendLine(string.Format("DEBUG: {0}",( (PSDataCollection<ProgressRecord>)sender )[e.Index]));
                            });
                        powershell.Streams.Verbose.DataAdded += new EventHandler<DataAddedEventArgs>(delegate(object sender, DataAddedEventArgs e)
                            {
                                sb.AppendLine(string.Format("VERBOSE: {0}",( (PSDataCollection<VerboseRecord>)sender )[e.Index]));
                            });
                        powershell.Streams.Warning.DataAdded += new EventHandler<DataAddedEventArgs>(delegate(object sender, DataAddedEventArgs e)
                            {
                                sb.AppendLine(string.Format("WARNING: {0}",( (PSDataCollection<WarningRecord>)sender )[e.Index]));
                            });
                        powershell.Streams.Error.DataAdded += new EventHandler<DataAddedEventArgs>(delegate(object sender, DataAddedEventArgs e)
                            {
                                sb.AppendLine(string.Format("ERROR: {0}", ((PSDataCollection<ErrorRecord>)sender)[e.Index]));
                            });

                        Collection<PSObject> outp =  powershell.Invoke();
                        foreach( PSObject o in outp )
                        {
                            sb.AppendLine(string.Format("{0}", o));
                        }

                        powershell.Stop();
                    }
                }

                try
                {
                    System.IO.File.AppendAllText("C:\\log.txt", sb.ToString());
                }
                catch
                {
                }

                this.Update();
                sw.Stop();

                using( SPSite s = Microsoft.SharePoint.Administration.SPAdministrationWebApplication.Local.Sites[0] )
                {
                    using( CaDataContext ca = new CaDataContext(s.Url) )
                    {
                        var list = ca.IngoKarsteinSSharePointPowerShellTimerJobHistory;
                        IngoKarsteinSSharePointPowerShellTimerJobHistory newEntry = new IngoKarsteinSSharePointPowerShellTimerJobHistory();
                        newEntry.Title = this.Name;
                        newEntry.EndTime = DateTime.Now;
                        newEntry.ErrorOccured = false;
                        newEntry.ResultText = sb.ToString();
                        newEntry.ServerName = SPServer.Local.Name;
                        newEntry.StartTime = start;
                        newEntry.Duration = sw.ElapsedMilliseconds;
                        list.InsertOnSubmit(newEntry);
                        ca.SubmitChanges();
                    }
                }
            }
            catch( Exception ex )
            {
                sw.Stop();
                using( SPSite s = Microsoft.SharePoint.Administration.SPAdministrationWebApplication.Local.Sites[0] )
                {
                    using( CaDataContext ca = new CaDataContext(s.Url) )
                    {
                        var list = ca.IngoKarsteinSSharePointPowerShellTimerJobHistory;
                        IngoKarsteinSSharePointPowerShellTimerJobHistory newEntry = new IngoKarsteinSSharePointPowerShellTimerJobHistory();
                        newEntry.Title = this.Name;
                        newEntry.EndTime = DateTime.Now;
                        newEntry.ErrorOccured = true;
                        newEntry.ResultText = ex.Message;
                        newEntry.ServerName = SPServer.Local.Name;
                        newEntry.StartTime = start;
                        newEntry.Duration = sw.ElapsedMilliseconds;
                        list.InsertOnSubmit(newEntry);
                        ca.SubmitChanges();
                    } 
                }
            }
            finally
            {
            }
        } 


        bool IPSApp.ShouldExit
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        int IPSApp.ExitCode
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        void IPSApp.Write(string s)
        {
            sb.Append(s);
        }

        void IPSApp.WriteLine(string s)
        {
            sb.AppendLine(s);
        }
    }
}
